import os
import unittest

from limber.documents import _filewrapper as filewrapper
from tests.mocks import *
from tests.tools import ConnectionBox

def setup_module():
    set_mockdir(2)

def testInstantiate():
    try:
        doc = filewrapper.FileWrapperDocument()
    except Exception, e:
        assert False, 'Could not instantiate the filewrapper: %r' % e


class TestFileWrapperDocument(unittest.TestCase):
    def setUp(self):
        self.document = filewrapper.FileWrapperDocument()
        self.mock_plain_path = os.path.join(get_systemdir(), 'mock_plain_text_file.txt')

    def testPlainTextFile(self):
        self.document.open(self.mock_plain_path, 'r')

        self.assertEqual(self.document.mode, 'r')
        self.assertEqual(self.document.tell(), 0)
        self.assertFalse(self.document.isatty())

        content = self.document.read()

        real_content = open(self.mock_plain_path).read()
        self.assertEqual(content, real_content)

    def testIsAtty(self):
        self.assertRaises(ValueError, self.document.isatty)
        self.document.open('file:///stdin')
        self.assertTrue(self.document.isatty())

    def testCanRead(self):
        self.assertFalse(self.document.can_read())
        self.document.open(self.mock_plain_path)
        self.assertTrue(self.document.can_read())

        document = filewrapper.FileWrapperDocument()
        document.open(self.mock_plain_path, 'a')
        self.assertFalse(document.can_read())

    def testCanWrite(self):
        self.assertFalse(self.document.can_write())
        self.document.open(self.mock_plain_path)
        self.assertFalse(self.document.can_write())

        document = filewrapper.FileWrapperDocument()
        document.open(self.mock_plain_path, 'a')
        self.assertTrue(document.can_write())

        document2 = filewrapper.FileWrapperDocument()
        document2.open(self.mock_plain_path, 'r+')
        self.assertTrue(document.can_write())

    def testClosedDocumentRaisesValueError(self):
        self.document.close()

        self.assertRaises(ValueError,
                          self.document.read, 1)

        self.assertRaises(ValueError,
                          self.document.write, 'test')

        self.assertRaises(ValueError,
                          self.document.tell)

        self.assertRaises(ValueError,
                          self.document.seek, 0)

        #multiple close calls does *not* raise ValueError
        self.document.close()

    def testDocumentRaisesIOErrorWhenWrongMode(self):
        fname = os.path.join(get_userdir(), 'mock_html_text_file.html')
        content = open(fname).read()

        self.document.open(fname)

        try:
            self.document.write('test')
        except IOError:
            new_content = open(fname).read()
            if new_content != content:
                assert False, 'Content changed even if IOError was raised'
        except Exception, e:
            new_content = open(fname).read()
            if new_content != content:
                fil = open(fname, 'w')
                fil.write(content)
                fil.close()

                fil = open('%s-modified' % (fname), 'w')
                fil.write(new_content)
                fil.close()

                detail = 'And the file changed content.'
            else:
                detail = ''

            self.fail('Unexpected exception: %r%s' % (e, detail))
        else:
            new_content = open(fname).read()
            if new_content != content:
                fil = open(fname, 'w')
                fil.write(content)
                fil.close()

                fil = open('%s-modified' % (fname), 'w')
                fil.write(new_content)
                fil.close()

                detail = 'And the file changed content.'
            else:
                detail = ''

            self.fail('Did not raise IOError.')

    def testDocumentEmitsDocumentModifiedSignals(self):
        box = ConnectionBox()
        self.document.document_modified.connect(box.slot)

        fname = os.path.join(get_userdir(),
                             'testDocumentEmitsDocumentModifiedSignals')
        self.document.open(fname, mode='w+')
        self.document.write('prova.\n')
        self.document.writelines(
            ['prova2.\n','prova3.\n','prova4.\n'])
        self.document.close()
        try:
            os.remove(fname)
        except (IOError,OSError):
            print 'WARNING!\nCould not remove the file created in the test!'

        self.assertEqual(box.signals_arrived, 2)



    def testDocumentEmitsDocumentSavedSignals(self):
        box = ConnectionBox()
        self.document.document_saved.connect(box.slot)

        fname = os.path.join(get_userdir(),
                             'testDocumentEmitsDocumentSavedSignals')
        self.document.open(fname, 'w+')
        self.document.save()
        self.document.write('prova.\n')
        self.document.save()

        self.document.close()
        try:
            os.remove(fname)
        except (IOError,OSError):
            print 'WARNING!\nCould not remove the file created in the test!'

        self.assertEqual(box.signals_arrived, 2)



    def testDocumentEmitsDocumentClosedSignals(self):
        box = ConnectionBox()
        self.document.document_closed.connect(box.slot)

        fname = os.path.join(get_userdir(),
                             'testDocumentEmitsDocumentClosedSignals')
        self.document.open(fname, 'w+')
        self.document.close()
        self.document.close()
        self.document.close()

        try:
            os.remove(fname)
        except (IOError,OSError):
            print 'WARNING!\nCould not remove the file created in the test!'

        self.assertEqual(box.signals_arrived, 1)


    def testDocumentEmitsDocumentOpenedSignals(self):
        box = ConnectionBox()
        self.document.document_loaded.connect(box.slot)

        fname = os.path.join(
            get_userdir(),
            'testDocumentEmitsDocumentOpenedSignals')

        self.document.open(fname, 'w+')
        self.document.close()

        try:
            os.remove(fname)
        except (IOError,OSError):
            print 'WARNING!\nCould not remove the file created in the test!'

        self.assertEqual(box.signals_arrived, 1)
